﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using scomA3proj.net.bing.api;
using System.Text.RegularExpressions;
using System.IO;
using System.Reflection;

namespace scomA3proj
{
    public class RequiredServices_James : IRequiredServices_James
    {



        #region --- WsdlDiscovery ---
        public string[] WsdlDiscovery(string keywords)
        {
            List<string> l = new List<string>();
            
            //Setup the Bing service object
            BingService service = new BingService();
            SearchRequest sr = new SearchRequest();
            //required: query, apid and sources
            sr.Query = keywords;
            sr.AppId = "00C7374610F83860122E5627F8D98B80715A4AFB";
            SourceType[] src = { SourceType.Web };
            sr.Sources = src;
            //create web result request and set reqeust count
            sr.Web = new WebRequest();
            sr.Web.Count = 30;
            sr.Web.CountSpecified = true;

            //Perform the search
            SearchResponse resp = service.Search(sr);
            
            //Iterate over the Bing result set.
            foreach(WebResult currResult in resp.Web.Results)
            {
                //Request the page's html
                string data = HttpRequestWrapper.getResponse(currResult.Url);
                //add the wsdl links found on the page to the result List
                l.AddRange(FindWSDLUrls(data));
            }
            
            return l.ToArray();
        }

        public string[] FindWSDLUrls(string input)
        {
            HashSet<string> l = new HashSet<string>();
            
            //The regex to match wsdl urls
            Regex r = new Regex(@"http(s?)://[a-zA-Z0-9\\.\\-_/]+(\\?[wW][sS][dD][lL][a-zA-Z0-9\\.\\-_/]*|\\.wsdl)");
            MatchCollection mc = r.Matches(input, 0);
            //add all matches to the list
            for (int i = 0; i < mc.Count; i++)
            {
                string res = mc[i].Value.Trim();
                //Filter out the obviously invalid web services like localhost and example.com
                if (res.Contains("://localhost") || res.Contains("://127.0.0.1") || res.Contains("://example.com") || res.Contains("://www.example.com"))
                    continue;

                l.Add(mc[i].Value.Trim());
            }
            return l.ToArray();
        }

        #endregion



        /// <summary>
        /// Number2Words
        /// 
        /// This service takes in a dictionary file "randomdictionary.txt" and creates an inverted index
        /// to mapping the number to the list of words that map to that number. The inverted index
        /// is mainly for simplicity and performance.
        /// 
        /// If our dictionary contained the words {"beg", "adg", "area"}
        /// our dictionary would be as follows:
        /// "234"->{"beg", "adg"}
        /// "2732"->{"area"}
        /// 
        /// With the inverted index created, we can try to find the longest substring that maps to
        /// a word in our inverted index. In the case that a number sequence maps to muliple words,
        /// a word is selected randomly from the word list for that number sequence.
        /// 
        /// When a sequence or portion of the sequence does not map to a word in our dictionary, 
        /// the number is kept.
        /// </summary>
        #region --- Number2Words ---

        

        
    
        
        public string Number2Words(string number)
        {
            Dictionary<string, List<string>> dict = new Dictionary<string, List<string>>();
            Random r = new Random();
            Stream stream = Assembly.GetExecutingAssembly()
                               .GetManifestResourceStream("scomA3proj.randomdictionary.txt");
            string[] lines = null;
            StreamReader reader = new StreamReader(stream);
            lines = reader.ReadToEnd().Split('\n');
            reader.Close();
            for (int i = 0; i < lines.Length; i++)
            {
                if (lines[i].Contains('\'')) continue;
                string nums = lettersToNumbers(lines[i].Trim());
                if (dict.ContainsKey(nums))
                {
                    List<string> tmp;
                    dict.TryGetValue(nums, out tmp);
                    tmp.Add(lines[i].Trim().ToLower());
                }
                else
                {
                    List<string> tmp = new List<string>();
                    tmp.Add(lines[i].Trim().ToLower());
                    dict.Add(nums, tmp);
                }
            }
            string res = "";
            if(number != null)
            {

                //string[] vals = Regex.Split(number, @"(0|1){1}");
                string[] vals = Regex.Split(number, @"(?<=[01])");
                for (int i = 0; i < vals.Length; i++)
                {
                    Console.Write(vals[i]);
                    string currWord = vals[i];
                    if (vals[i] == "0" || vals[i] == "1" || vals[i] == "")
                    {
                        res += vals[i];
                        continue;
                    }

                    for (int startIndex = 0; startIndex < currWord.Length; startIndex++)
                    {
                        bool wordFound = false;
                        for (int endIndex = currWord.Length; endIndex >= startIndex; endIndex--)
                        {
                            string subs = currWord.Substring(startIndex, endIndex - startIndex);
                            string word = lookupRandomWord(subs, dict, r);
                            if (word != null)
                            {
                                res += word;
                                startIndex = endIndex - 1;
                                wordFound = true;
                            }
                        }
                        if (!wordFound)
                        {
                            res += currWord[startIndex];
                        }
                    }
                }
            }
            else return "";
            

            return res;
        }


        private static string lookupRandomWord(string nums, Dictionary<string, List<string>> dict, Random r)
        {
            List<string> tmp;
            
            if (dict.TryGetValue(nums, out tmp))
            {
                return tmp[r.Next(0, tmp.Count - 1)];
            }
            return null;
        }

        private static string lettersToNumbers(string s)
        {
            s = s.ToLower();
            string res = "";
            for (int i = 0; i < s.Length; i++)
            {
                switch (s[i])
                {
                    case 'a':
                    case 'b':
                    case 'c':
                        res += "2";
                        break;
                    case 'd':
                    case 'e':
                    case 'f':
                        res += "3";
                        break;
                    case 'g':
                    case 'h':
                    case 'i':
                        res += "4";
                        break;
                    case 'j':
                    case 'k':
                    case 'l':
                        res += "5";
                        break;
                    case 'm':
                    case 'n':
                    case 'o':
                        res += "6";
                        break;
                    case 'p':
                    case 'q':
                    case 'r':
                    case 's':
                        res += "7";
                        break;
                    case 't':
                    case 'u':
                    case 'v':
                        res += "8";
                        break;
                    case 'w':
                    case 'x':
                    case 'y':
                    case 'z':
                        res += "9";
                        break;
                    default:
                        res += s[i];
                        break;
                        
                }
            }
            return res;

        }

        #endregion
    }
}
